package com.snda.lib.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Environment;

public class ImageDownloader {

	private static ConcurrentMap<String, SoftReference<Bitmap>> bmpCache = new ConcurrentHashMap<String, SoftReference<Bitmap>>();
	private static List<String> loadingTask = new ArrayList<String>();

	public static Bitmap loadImage(final Context context,
			final String strImageUrl, final String strCacheDir,
			final Callback callback) {

		final String strFileName = MD5Helper.getStringMD5(strImageUrl) + ".png";

		if (bmpCache.containsKey(strFileName)) {
			SoftReference<Bitmap> softReference = bmpCache.get(strFileName);
			Bitmap bmp = softReference.get();
			if (bmp != null) {
				return bmp;
			}
		}

		if (FileHelper.judgeFileExist(context, strCacheDir, strFileName)) {
			Bitmap bmp = loadBitmapFromSD(context, strCacheDir, strFileName);
			if (bmp != null) {
				bmpCache.put(strFileName, new SoftReference<Bitmap>(bmp));
				return bmp;
			}
		}
		if (loadingTask.contains(strFileName)) {
			return null;
		}

		ConnectivityManager cm = (ConnectivityManager) context
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo ni = cm.getActiveNetworkInfo();
		if (ni == null) {
			return null;// no network
		}

		loadingTask.add(strFileName);

		AsyncTask<String, Integer, Bitmap> asyncLoadImageTask = new AsyncTask<String, Integer, Bitmap>() {

			@Override
			protected Bitmap doInBackground(String... params) {
				Bitmap bmp;
				if (Environment.getExternalStorageState().equals(
						Environment.MEDIA_MOUNTED)) {
					bmp = downloadImageToSD(context, strImageUrl, strCacheDir,
							strFileName);
				} else {
					bmp = downloadBitmap(context, strImageUrl);
				}
				if (bmp != null) {
					bmpCache.put(strFileName, new SoftReference<Bitmap>(bmp));
				}
				return bmp;
			}

			@Override
			protected void onPostExecute(Bitmap result) {
				if (callback != null) {
					callback.imageLoaded(result, strImageUrl);
				}
				loadingTask.remove(strFileName);
			}
		};
		asyncLoadImageTask.execute();
		return null;
	}

	/**
	 * 下载图片并保存的sd卡文件中
	 * 
	 * @param imageUrl
	 * @param path
	 * @param fileName
	 * @return
	 */
	private static Bitmap downloadImageToSD(Context context, String imageUrl,
			String path, String fileName) {
		URL url = null;
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		try {
			url = new URL(imageUrl);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(30000);
			conn.setReadTimeout(30000);
			bis = new BufferedInputStream(conn.getInputStream());
			bos = new BufferedOutputStream(new FileOutputStream(new File(path,
					fileName)));
			byte[] buf = new byte[1024];
			int len = 0;
			while ((len = bis.read(buf)) > 0) {
				bos.write(buf, 0, len);
			}
			conn.disconnect();

		} catch (MalformedURLException e) {
			e.printStackTrace();
			return null;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		} finally {
			try {
				if (bis != null) {
					bis.close();
				}
				if (bos != null) {
					bos.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		FileInputStream is = null;
		try {
			is = new FileInputStream(new File(path, fileName));
			return loadBitmap(context, is);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return null;
	}

	private static Bitmap downloadBitmap(Context context, String imageUrl) {
		URL url = null;
		InputStream is = null;
		try {
			url = new URL(imageUrl);
			is = url.openStream();
			return loadBitmap(context, is);
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return null;
	}

	private static Bitmap loadBitmap(Context context, InputStream is) {
		Bitmap bmp = null;
		BitmapFactory.Options opts = new BitmapFactory.Options();
		opts.inPreferredConfig = Bitmap.Config.RGB_565;
		bmp = BitmapFactory.decodeStream(is, null, opts);
		return bmp;
	}

	private static Bitmap loadBitmapFromSD(Context context, String path,
			String fileName) {
		InputStream is = null;
		try {
			is = new FileInputStream(new File(path, fileName));
			return loadBitmap(context, is);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return null;
	}

	public interface Callback {
		public void imageLoaded(Bitmap bitmap, String imageUrl);
	}
}